package pers.kw.service.impl;

import com.alibaba.nacos.common.utils.IoUtils;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import pers.kw.config.minio.MinioConfig;
import pers.kw.protocol.R;
import pers.kw.service.FileService;
import pers.kw.utils.FileUploadUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

@Slf4j
@Primary
@Service
public class MinioFileServiceImpl implements FileService {

    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private MinioClient minioClient;

    @Override
    public R<String> uploadFile(MultipartFile file) throws Exception {
        String fileName = FileUploadUtils.extractFilename(file);
        InputStream inputStream = file.getInputStream();
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName)
                .stream(inputStream, file.getSize(), -1)
                .contentType(file.getContentType())
                .build();
        minioClient.putObject(args);
        IoUtils.closeQuietly(inputStream);
        //访问策略公开的bucket才可以这么访问
        String url = minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
        return R.ok(url);
    }

    @Override
    public void downloadFile(HttpServletResponse httpServletResponse, String fileName) throws Exception {
        GetObjectArgs.Builder builder = GetObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName);
        InputStream inputStream = minioClient.getObject(builder.build());
        //byte[] bytes = IOUtils.toByteArray(inputStream);
        // 清空response
        httpServletResponse.reset();
        // 设置response的Header
        httpServletResponse.setCharacterEncoding("UTF-8");
        //Content-Disposition的作用：告知浏览器以何种方式显示响应返回的文件，用浏览器打开还是以附件的形式下载到本地保存
        //attachment表示以附件方式下载   inline表示在线打开   "Content-Disposition: inline; filename=文件名.mp3"
        // filename表示文件的默认名称，因为网络传输只支持URL编码的相关支付，因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
        httpServletResponse.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        // 告知浏览器文件的大小
        //httpServletResponse.addHeader("Content-Length", "" + inputStream.length());
        OutputStream outputStream = new BufferedOutputStream(httpServletResponse.getOutputStream());
        httpServletResponse.setContentType("application/octet-stream");
        byte[] b = new byte[1024];
        int len;
        //从输入流中读取一定数量的字节，并将其存储在缓冲区字节数组中，读到末尾返回-1
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }
        outputStream.flush();
    }

    @Override
    public R<String> getFileExpiryAccessUrl(String fileName) throws Exception {
        GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
                .method(Method.GET)
                .bucket(minioConfig.getBucketName())
                .object(fileName)
                //默认七天，单位秒
                .expiry(60)   //生成的预签名url可访问的有效时间，最大期限7天
                .build();
        String url = minioClient.getPresignedObjectUrl(build);
        return R.ok(url);
    }
    //过60再次访问url，提示： Request has expired
    //参考https://blog.csdn.net/yy339452689/article/details/126410894
}
